import os
import pprint
import configparser
import time

from PySide6 import QtCore, QtGui, QtWidgets

import ui_BesEqEditor
from BesEqEditor import EqEditor


CURRENT_DIR = os.getcwd()
TEMP_CONFIG_FILE_NAME = "config_bes_eq_editor.ini"
TEMP_CONFIG_FILE_PATH = os.path.join(CURRENT_DIR, TEMP_CONFIG_FILE_NAME)
TEMP_CONFIG_FILE_SECTION_NAME = "BES_EQ_EDITOR"
TEMP_CONFIG_FILE_KEY_APP_BIN_PATH = "APP_BIN_PATH"
TEMP_CONFIG_FILE_KEY_MAP_FILE_PATH = "MAP_FILE_PATH"
TEMP_CONFIG_FILE_KEY_CFG_FILE_PATH = "CFG_FILE_PATH"
TEMP_CONFIG_FILE_KEY_NEW_APP_BIN_PATH = "NEW_APP_BIN_PATH"


LEVEL_ERROR = '[Error]'
LEVEL_INFO = '[Info]'
LEVEL_WARN = '[Warning]'


class MainWidget(QtWidgets.QWidget, ui_BesEqEditor.Ui_BesEqEditor):
    def __init__(self):
        super().__init__()
        self.eq_editor = EqEditor()
        self.setupUi(self)
        self._init_signal_connect()
        self._init_default_state()

    def _print_log(self, level, msg):
        def time_str():
            return time.strftime('%Y-%m-%d %H:%M:%S  ', time.localtime())
        log_msg = time_str() + level + ': ' + str(msg)
        self.log_broswer.append(log_msg)
        self.log_broswer.moveCursor(QtGui.QTextCursor.End)

    def _init_signal_connect(self):
        self.app_bin_select_button.clicked.connect(self._app_bin_select_button_click)
        self.app_bin_get_param_button.clicked.connect(self._app_bin_get_param_button_click)
        self.app_bin_save_param_button.clicked.connect(self._app_bin_set_param_button_click)

        self.map_file_select_button.clicked.connect(self._map_file_select_button_click)
        self.map_file_get_info_button.clicked.connect(self._map_file_get_info_button_click)

        self.cfg_file_select_button.clicked.connect(self._cfg_file_select_button_click)
        self.cfg_file_get_info_button.clicked.connect(self._cfg_file_get_info_button_click)
        self.cfg_file_save_info_button.clicked.connect(self._cfg_file_set_info_button_click)

        self.new_app_bin_select_button.clicked.connect(self._new_app_bin_select_button_click)
        self.new_app_bin_get_param_button.clicked.connect(self._new_app_bin_get_param_button_click)

        self.params_reset_button.clicked.connect(self._params_reset_button_click)

        self.project_name.currentIndexChanged.connect(self._project_name_combo_box_index_changed)
        self.eq_name.currentIndexChanged.connect(self._eq_name_combo_box_index_changed)

        self.app_bin_path.textChanged.connect(self._app_bin_path_changed)
        self.map_file_path.textChanged.connect(self._map_file_path_changed)
        self.cfg_file_path.textChanged.connect(self._cfg_file_path_changed)
        self.new_app_bin_path.textChanged.connect(self._new_app_bin_path_changed)

        self.log_clear_button.clicked.connect(self._log_clear_button_click)

    def _init_default_state(self):
        eq_editor = self.eq_editor
        valid_project_cfg = eq_editor.get_valid_project_config()
        if not valid_project_cfg:
            return None
        project_names = list(valid_project_cfg.keys())
        if not project_names:
            return None
        self.project_name.addItems(project_names)
        self.project_name.setCurrentIndex(0)

        app_bin_path = self._get_ui_config_from_temp_file(TEMP_CONFIG_FILE_SECTION_NAME, TEMP_CONFIG_FILE_KEY_APP_BIN_PATH)
        if app_bin_path:
            self.app_bin_path.setText(app_bin_path)
        map_bin_path = self._get_ui_config_from_temp_file(TEMP_CONFIG_FILE_SECTION_NAME, TEMP_CONFIG_FILE_KEY_MAP_FILE_PATH)
        if map_bin_path:
            self.map_file_path.setText(map_bin_path)
        cfg_file_path = self._get_ui_config_from_temp_file(TEMP_CONFIG_FILE_SECTION_NAME, TEMP_CONFIG_FILE_KEY_CFG_FILE_PATH)
        if cfg_file_path:
            self.cfg_file_path.setText(cfg_file_path)
        new_app_bin_path = self._get_ui_config_from_temp_file(TEMP_CONFIG_FILE_SECTION_NAME, TEMP_CONFIG_FILE_KEY_NEW_APP_BIN_PATH)
        if new_app_bin_path:
            self.new_app_bin_path.setText(new_app_bin_path)

    @QtCore.Slot()
    def _app_bin_select_button_click(self):
        self._print_log(LEVEL_INFO, "_app_bin_select_button_click")
        current_path = self.app_bin_path.text().strip()
        current_path = os.path.dirname(current_path)
        absolute_path = QtWidgets.QFileDialog.getOpenFileName(self, "打开一个APP BIN文件", current_path, "(*.bin);;(*)")
        self.app_bin_path.setText(absolute_path[0])

    @QtCore.Slot()
    def _app_bin_get_param_button_click(self):
        self._print_log(LEVEL_INFO, "_app_bin_get_param_button_click")
        bin_path = self.app_bin_path.text().strip()
        if (not bin_path) or (not os.path.isfile(bin_path)):
            self._print_log(LEVEL_WARN, "app bin get param [Failed], cannot find valid app bin path.")
            return None
        map_path = self.map_file_path.text().strip()
        if (not map_path) or (not os.path.isfile(map_path)):
            self._print_log(LEVEL_WARN, "app bin get param [Failed], cannot find valid map file path.")
            return None
        project_name = self.project_name.currentText()
        if not project_name:
            self._print_log(LEVEL_WARN, "app bin get param [Failed], cannot find valid project_name.")
            return None
        eq_name = self.eq_name.currentText()
        if not eq_name:
            self._print_log(LEVEL_WARN, "app bin get param [Failed], cannot find valid eq_name.")
            return None
        eq_editor = EqEditor()
        struct_list = eq_editor.read_from_bin(bin_path, map_path, project_name, eq_name=eq_name)
        if not struct_list:
            self._print_log(LEVEL_WARN, "app bin get param [Failed], read from bin fail.")
            return None
        result = self._write_all_configs_to_ui(struct_list)
        if not result:
            self._print_log(LEVEL_WARN, "app bin get param [Failed], write params to ui failed.")
            return None
        else:
            self._print_log(LEVEL_INFO, "app bin get param [Successful].")
            return struct_list

    @QtCore.Slot()
    def _app_bin_set_param_button_click(self):
        self._print_log(LEVEL_INFO, "_app_bin_set_param_button_click")
        eq_editor = EqEditor()
        bin_path_old = self.app_bin_path.text().strip()
        if (not bin_path_old) or (not os.path.isfile(bin_path_old)):
            self._print_log(LEVEL_WARN, "app bin set param [Failed], cannot find valid app bin path.")
            return None
        bin_path_new = self.new_app_bin_path.text().strip()
        if not bin_path_new:
            self._print_log(LEVEL_WARN, "app bin set param [Failed], cannot find valid new app bin path.")
            return None
        map_path = self.map_file_path.text().strip()
        if (not map_path) or (not os.path.isfile(map_path)):
            self._print_log(LEVEL_WARN, "app bin set param [Failed], cannot find valid valid file path.")
            return None
        project_name = self.project_name.currentText()
        if not project_name:
            self._print_log(LEVEL_WARN, "app bin set param [Failed], cannot find valid project_name.")
            return None
        eq_name = self.eq_name.currentText()
        if not eq_name:
            self._print_log(LEVEL_WARN, "app bin set param [Failed], cannot find valid eq_name.")
            return None
        struct_list = self._read_all_configs_from_ui()
        if not struct_list:
            self._print_log(LEVEL_WARN, "app bin set param [Failed], read config from ui fail.")
            return None
        result = eq_editor.write_to_bin(struct_list, bin_path_old, bin_path_new, map_path, project_name, eq_name)
        if not result:
            self._print_log(LEVEL_WARN, "app bin set param [Failed], write to bin fail.")
            return None
        else:
            self._print_log(LEVEL_INFO, "app bin set param [Successful].")
            return struct_list

    @QtCore.Slot()
    def _map_file_select_button_click(self):
        self._print_log(LEVEL_INFO, "_map_file_select_button_click")
        current_path = self.app_bin_path.text().strip()
        current_path = os.path.dirname(current_path)
        absolute_path = QtWidgets.QFileDialog.getOpenFileName(self, "打开map文件", current_path, "(*.map);;(*)")
        self.map_file_path.setText(absolute_path[0])

    @QtCore.Slot()
    def _map_file_get_info_button_click(self):
        self._print_log(LEVEL_INFO, "_map_file_get_info_button_click")

    @QtCore.Slot()
    def _cfg_file_select_button_click(self):
        self._print_log(LEVEL_INFO, "_cfg_file_select_button_click")
        current_path = self.app_bin_path.text().strip()
        current_path = os.path.dirname(current_path)
        absolute_path = QtWidgets.QFileDialog.getOpenFileName(self, "打开eq配置文件", current_path, "(*.cfg);;(*)")
        self.cfg_file_path.setText(absolute_path[0])

    @QtCore.Slot()
    def _cfg_file_get_info_button_click(self):
        self._print_log(LEVEL_INFO, "_cfg_file_get_info_button_click")
        cfg_file_path = self.cfg_file_path.text().strip()
        if (not cfg_file_path) or (not os.path.isfile(cfg_file_path)):
            self._print_log(LEVEL_WARN, "cfg file get info [Failed], please set correct cfg file path: [{}]".format(cfg_file_path))
            return None
        eq_editor = self.eq_editor
        struct_list  = eq_editor.read_from_config_file(cfg_file_path)
        if not struct_list:
            self._print_log(LEVEL_WARN, "cfg file get info [Failed], read from cfg file fail. path: [{}]".format(cfg_file_path))
            return None
        result = self._write_all_configs_to_ui(struct_list)
        if not result:
            self._print_log(LEVEL_WARN, "cfg file get info [Failed], write cfg to ui failed.")
            return None
        else:
            self._print_log(LEVEL_INFO, "cfg file get info [Successful].")
            return struct_list

    @QtCore.Slot()
    def _cfg_file_set_info_button_click(self):
        self._print_log(LEVEL_INFO, "_cfg_file_set_info_button_click")
        struct_list = self._read_all_configs_from_ui()
        if not struct_list:
            self._print_log(LEVEL_WARN, "cfg file set info [Failed], read config from ui fail.")
            return None
        save_path = self.cfg_file_path.text()
        if not save_path.strip():
            self._print_log(LEVEL_WARN, "cfg file set info [Failed], No valid save_path found.")
            return None
        project_name = self.project_name.currentText()
        if not project_name.strip():
            self._print_log(LEVEL_WARN, "cfg file set info [Failed], No valid project_name found.")
            return None
        eq_name = self.eq_name.currentText()
        if not eq_name.strip():
            self._print_log(LEVEL_WARN, "cfg file set info [Failed], No valid eq name found.")
            return None
        struct_name = self.struct_name.text()
        if not struct_name.strip():
            self._print_log(LEVEL_WARN, "cfg file set info [Failed], No valid struct_name found.")
            return None
        eq_editor = self.eq_editor
        # pprint.pprint("_cfg_file_set_info_button_click print struct_list")
        # pprint.pprint(struct_list)
        result = eq_editor.write_to_config_file(struct_list, save_path, project_name, eq_name=eq_name)
        if not result:
            self._print_log(LEVEL_WARN, "cfg file set info [Failed], write to cfg file failed.")
            return None
        else:
            self._print_log(LEVEL_INFO, "cfg file set info [Successful]")
            return result

    @QtCore.Slot()
    def _new_app_bin_select_button_click(self):
        self._print_log(LEVEL_INFO, "_new_app_bin_select_button_click")
        current_path = self.app_bin_path.text().strip()
        current_path = os.path.dirname(current_path)
        absolute_path = QtWidgets.QFileDialog.getOpenFileName(self, "打开需要保存的BIN文件路径", current_path, "(*.bin);;(*)")
        self.new_app_bin_path.setText(absolute_path[0])

    @QtCore.Slot()
    def _new_app_bin_get_param_button_click(self):
        self._print_log(LEVEL_INFO, "_app_bin_get_param_button_click")
        bin_path = self.new_app_bin_path.text().strip()
        if (not bin_path) or (not os.path.isfile(bin_path)):
            self._print_log(LEVEL_WARN, "app bin get param [Failed], cannot find valid app bin path.")
            return None
        map_path = self.map_file_path.text().strip()
        if (not map_path) or (not os.path.isfile(map_path)):
            self._print_log(LEVEL_WARN, "app bin get param [Failed], cannot find valid map file path.")
            return None
        project_name = self.project_name.currentText()
        if not project_name:
            self._print_log(LEVEL_WARN, "app bin get param [Failed], cannot find valid project_name.")
            return None
        eq_name = self.eq_name.currentText()
        if not eq_name:
            self._print_log(LEVEL_WARN, "app bin get param [Failed], cannot find valid eq_name.")
            return None
        eq_editor = EqEditor()
        struct_list = eq_editor.read_from_bin(bin_path, map_path, project_name, eq_name=eq_name)
        if not struct_list:
            self._print_log(LEVEL_WARN, "app bin get param [Failed], read from bin fail.")
            return None
        result = self._write_all_configs_to_ui(struct_list)
        if not result:
            self._print_log(LEVEL_WARN, "app bin get param [Failed], write params to ui failed.")
            return None
        else:
            self._print_log(LEVEL_INFO, "app bin get param [Successful].")
            return struct_list

    @QtCore.Slot()
    def _params_reset_button_click(self):
        self._print_log(LEVEL_INFO, "_params_reset_button_click")
        self.eq_gain0.setValue(0)
        self.eq_gain1.setValue(0)
        self.eq_num.setValue(0)

        self.eq_param_0_type.setCurrentIndex(-1)
        self.eq_param_0_gain.setValue(0)
        self.eq_param_0_fc.setValue(0)
        self.eq_param_0_q.setValue(0)

        self.eq_param_1_type.setCurrentIndex(-1)
        self.eq_param_1_gain.setValue(0)
        self.eq_param_1_fc.setValue(0)
        self.eq_param_1_q.setValue(0)

        self.eq_param_2_type.setCurrentIndex(-1)
        self.eq_param_2_gain.setValue(0)
        self.eq_param_2_fc.setValue(0)
        self.eq_param_2_q.setValue(0)

        self.eq_param_3_type.setCurrentIndex(-1)
        self.eq_param_3_gain.setValue(0)
        self.eq_param_3_fc.setValue(0)
        self.eq_param_3_q.setValue(0)

        self.eq_param_4_type.setCurrentIndex(-1)
        self.eq_param_4_gain.setValue(0)
        self.eq_param_4_fc.setValue(0)
        self.eq_param_4_q.setValue(0)

        self.eq_param_5_type.setCurrentIndex(-1)
        self.eq_param_5_gain.setValue(0)
        self.eq_param_5_fc.setValue(0)
        self.eq_param_5_q.setValue(0)

        self.eq_param_6_type.setCurrentIndex(-1)
        self.eq_param_6_gain.setValue(0)
        self.eq_param_6_fc.setValue(0)
        self.eq_param_6_q.setValue(0)

        self.eq_param_7_type.setCurrentIndex(-1)
        self.eq_param_7_gain.setValue(0)
        self.eq_param_7_fc.setValue(0)
        self.eq_param_7_q.setValue(0)

        self.eq_param_8_type.setCurrentIndex(-1)
        self.eq_param_8_gain.setValue(0)
        self.eq_param_8_fc.setValue(0)
        self.eq_param_8_q.setValue(0)

        self.eq_param_9_type.setCurrentIndex(-1)
        self.eq_param_9_gain.setValue(0)
        self.eq_param_9_fc.setValue(0)
        self.eq_param_9_q.setValue(0)

        self.eq_param_10_type.setCurrentIndex(-1)
        self.eq_param_10_gain.setValue(0)
        self.eq_param_10_fc.setValue(0)
        self.eq_param_10_q.setValue(0)

        self.eq_param_11_type.setCurrentIndex(-1)
        self.eq_param_11_gain.setValue(0)
        self.eq_param_11_fc.setValue(0)
        self.eq_param_11_q.setValue(0)

        self.eq_param_12_type.setCurrentIndex(-1)
        self.eq_param_12_gain.setValue(0)
        self.eq_param_12_fc.setValue(0)
        self.eq_param_12_q.setValue(0)

        self.eq_param_13_type.setCurrentIndex(-1)
        self.eq_param_13_gain.setValue(0)
        self.eq_param_13_fc.setValue(0)
        self.eq_param_13_q.setValue(0)

        self.eq_param_14_type.setCurrentIndex(-1)
        self.eq_param_14_gain.setValue(0)
        self.eq_param_14_fc.setValue(0)
        self.eq_param_14_q.setValue(0)

        self.eq_param_15_type.setCurrentIndex(-1)
        self.eq_param_15_gain.setValue(0)
        self.eq_param_15_fc.setValue(0)
        self.eq_param_15_q.setValue(0)

        self.eq_param_16_type.setCurrentIndex(-1)
        self.eq_param_16_gain.setValue(0)
        self.eq_param_16_fc.setValue(0)
        self.eq_param_16_q.setValue(0)

        self.eq_param_17_type.setCurrentIndex(-1)
        self.eq_param_17_gain.setValue(0)
        self.eq_param_17_fc.setValue(0)
        self.eq_param_17_q.setValue(0)

        self.eq_param_18_type.setCurrentIndex(-1)
        self.eq_param_18_gain.setValue(0)
        self.eq_param_18_fc.setValue(0)
        self.eq_param_18_q.setValue(0)

        self.eq_param_19_type.setCurrentIndex(-1)
        self.eq_param_19_gain.setValue(0)
        self.eq_param_19_fc.setValue(0)
        self.eq_param_19_q.setValue(0)

    @QtCore.Slot()
    def _log_clear_button_click(self):
        self.log_broswer.clear()
        self.log_broswer.moveCursor(QtGui.QTextCursor.Start)

    @QtCore.Slot()
    def _project_name_combo_box_index_changed(self):
        eq_editor = self.eq_editor
        valid_project_cfg = eq_editor.get_valid_project_config()
        if not valid_project_cfg:
            return None
        project_name = self.project_name.currentText()
        project_configs = valid_project_cfg.get(project_name)
        if not project_configs:
            return None
        self.eq_name.setCurrentIndex(0)
        self.eq_name.clear()
        for config in project_configs:
            eq_name = config.get('eq_name')
            self.eq_name.addItem(eq_name)

    @QtCore.Slot()
    def _eq_name_combo_box_index_changed(self):
        eq_editor = self.eq_editor
        valid_project_cfg = eq_editor.get_valid_project_config()
        if not valid_project_cfg:
            return None
        project_name = self.project_name.currentText()
        project_configs = valid_project_cfg.get(project_name)
        if not project_configs:
            return None
        eq_name = self.eq_name.currentText()
        struct_name = eq_editor.get_struct_name_by_eq_name(eq_name, project_name)
        self.struct_name.setText(struct_name)

    @QtCore.Slot()
    def _app_bin_path_changed(self):
        self._print_log(LEVEL_INFO, "_app_bin_path_changed")
        app_bin_path = self.app_bin_path.text().strip()
        self._save_ui_config_to_temp_file(TEMP_CONFIG_FILE_SECTION_NAME, TEMP_CONFIG_FILE_KEY_APP_BIN_PATH, app_bin_path)
        path = os.path.splitext(app_bin_path)[0]
        attr = os.path.splitext(app_bin_path)[1]
        new_app_bin_path = path + "_new" + attr
        self.new_app_bin_path.setText(new_app_bin_path)

    @QtCore.Slot()
    def _map_file_path_changed(self):
        map_file_path = self.map_file_path.text().strip()
        self._save_ui_config_to_temp_file(TEMP_CONFIG_FILE_SECTION_NAME, TEMP_CONFIG_FILE_KEY_MAP_FILE_PATH, map_file_path)

    @QtCore.Slot()
    def _cfg_file_path_changed(self):
        cfg_file_path = self.cfg_file_path.text().strip()
        self._save_ui_config_to_temp_file(TEMP_CONFIG_FILE_SECTION_NAME, TEMP_CONFIG_FILE_KEY_CFG_FILE_PATH, cfg_file_path)

    @QtCore.Slot()
    def _new_app_bin_path_changed(self):
        new_app_bin_path = self.new_app_bin_path.text().strip()
        self._save_ui_config_to_temp_file(TEMP_CONFIG_FILE_SECTION_NAME, TEMP_CONFIG_FILE_KEY_NEW_APP_BIN_PATH, new_app_bin_path)

    def _read_all_configs_from_ui(self):
        eq_editor = self.eq_editor
        struct_list = []
        struct_list.append(float(self.eq_gain0.text())) # gain0
        struct_list.append(float(self.eq_gain1.text())) # gain1
        struct_list.append(int(self.eq_num.text())) # num
        params = []
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_0_type.currentText()),
                            float(self.eq_param_0_gain.text()),
                            float(self.eq_param_0_fc.text()),
                            float(self.eq_param_0_q.text())])
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_1_type.currentText()),
                            float(self.eq_param_1_gain.text()),
                            float(self.eq_param_1_fc.text()),
                            float(self.eq_param_1_q.text())])
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_2_type.currentText()),
                            float(self.eq_param_2_gain.text()),
                            float(self.eq_param_2_fc.text()),
                            float(self.eq_param_2_q.text())])
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_3_type.currentText()),
                            float(self.eq_param_3_gain.text()),
                            float(self.eq_param_3_fc.text()),
                            float(self.eq_param_3_q.text())])
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_4_type.currentText()),
                            float(self.eq_param_4_gain.text()),
                            float(self.eq_param_4_fc.text()),
                            float(self.eq_param_4_q.text())])
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_5_type.currentText()),
                            float(self.eq_param_5_gain.text()),
                            float(self.eq_param_5_fc.text()),
                            float(self.eq_param_5_q.text())])
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_6_type.currentText()),
                            float(self.eq_param_6_gain.text()),
                            float(self.eq_param_6_fc.text()),
                            float(self.eq_param_6_q.text())])
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_7_type.currentText()),
                            float(self.eq_param_7_gain.text()),
                            float(self.eq_param_7_fc.text()),
                            float(self.eq_param_7_q.text())])
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_8_type.currentText()),
                            float(self.eq_param_8_gain.text()),
                            float(self.eq_param_8_fc.text()),
                            float(self.eq_param_8_q.text())])
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_9_type.currentText()),
                            float(self.eq_param_9_gain.text()),
                            float(self.eq_param_9_fc.text()),
                            float(self.eq_param_9_q.text())])
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_10_type.currentText()),
                            float(self.eq_param_10_gain.text()),
                            float(self.eq_param_10_fc.text()),
                            float(self.eq_param_10_q.text())])
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_11_type.currentText()),
                            float(self.eq_param_11_gain.text()),
                            float(self.eq_param_11_fc.text()),
                            float(self.eq_param_11_q.text())])
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_12_type.currentText()),
                            float(self.eq_param_12_gain.text()),
                            float(self.eq_param_12_fc.text()),
                            float(self.eq_param_12_q.text())])
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_13_type.currentText()),
                            float(self.eq_param_13_gain.text()),
                            float(self.eq_param_13_fc.text()),
                            float(self.eq_param_13_q.text())])
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_14_type.currentText()),
                            float(self.eq_param_14_gain.text()),
                            float(self.eq_param_14_fc.text()),
                            float(self.eq_param_14_q.text())])
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_15_type.currentText()),
                            float(self.eq_param_15_gain.text()),
                            float(self.eq_param_15_fc.text()),
                            float(self.eq_param_15_q.text())])
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_16_type.currentText()),
                            float(self.eq_param_16_gain.text()),
                            float(self.eq_param_16_fc.text()),
                            float(self.eq_param_16_q.text())])
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_17_type.currentText()),
                            float(self.eq_param_17_gain.text()),
                            float(self.eq_param_17_fc.text()),
                            float(self.eq_param_17_q.text())])
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_18_type.currentText()),
                            float(self.eq_param_18_gain.text()),
                            float(self.eq_param_18_fc.text()),
                            float(self.eq_param_18_q.text())])
        params.append([eq_editor.iir_type_t_convert_string_to_int(self.eq_param_19_type.currentText()),
                            float(self.eq_param_19_gain.text()),
                            float(self.eq_param_19_fc.text()),
                            float(self.eq_param_19_q.text())])
        struct_list.append(params)
        # pprint.pprint(struct_list)
        return struct_list

    def _write_all_configs_to_ui(self, struct_list):
        eq_editor = self.eq_editor
        self.eq_gain0.setValue(struct_list[0])
        self.eq_gain1.setValue(struct_list[1])
        self.eq_num.setValue(struct_list[2])

        params = struct_list[3]
        self.eq_param_0_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[0][0]))
        self.eq_param_0_gain.setValue(params[0][1])
        self.eq_param_0_fc.setValue(params[0][2])
        self.eq_param_0_q.setValue(params[0][3])

        self.eq_param_1_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[1][0]))
        self.eq_param_1_gain.setValue(params[1][1])
        self.eq_param_1_fc.setValue(params[1][2])
        self.eq_param_1_q.setValue(params[1][3])

        self.eq_param_2_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[2][0]))
        self.eq_param_2_gain.setValue(params[2][1])
        self.eq_param_2_fc.setValue(params[2][2])
        self.eq_param_2_q.setValue(params[2][3])

        self.eq_param_3_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[3][0]))
        self.eq_param_3_gain.setValue(params[3][1])
        self.eq_param_3_fc.setValue(params[3][2])
        self.eq_param_3_q.setValue(params[3][3])

        self.eq_param_4_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[4][0]))
        self.eq_param_4_gain.setValue(params[4][1])
        self.eq_param_4_fc.setValue(params[4][2])
        self.eq_param_4_q.setValue(params[4][3])

        self.eq_param_5_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[5][0]))
        self.eq_param_5_gain.setValue(params[5][1])
        self.eq_param_5_fc.setValue(params[5][2])
        self.eq_param_5_q.setValue(params[5][3])

        self.eq_param_6_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[6][0]))
        self.eq_param_6_gain.setValue(params[6][1])
        self.eq_param_6_fc.setValue(params[6][2])
        self.eq_param_6_q.setValue(params[6][3])

        self.eq_param_7_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[7][0]))
        self.eq_param_7_gain.setValue(params[7][1])
        self.eq_param_7_fc.setValue(params[7][2])
        self.eq_param_7_q.setValue(params[7][3])

        self.eq_param_8_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[8][0]))
        self.eq_param_8_gain.setValue(params[8][1])
        self.eq_param_8_fc.setValue(params[8][2])
        self.eq_param_8_q.setValue(params[8][3])

        self.eq_param_9_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[9][0]))
        self.eq_param_9_gain.setValue(params[9][1])
        self.eq_param_9_fc.setValue(params[9][2])
        self.eq_param_9_q.setValue(params[9][3])

        self.eq_param_10_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[10][0]))
        self.eq_param_10_gain.setValue(params[10][1])
        self.eq_param_10_fc.setValue(params[10][2])
        self.eq_param_10_q.setValue(params[10][3])

        self.eq_param_11_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[11][0]))
        self.eq_param_11_gain.setValue(params[11][1])
        self.eq_param_11_fc.setValue(params[11][2])
        self.eq_param_11_q.setValue(params[11][3])

        self.eq_param_12_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[12][0]))
        self.eq_param_12_gain.setValue(params[12][1])
        self.eq_param_12_fc.setValue(params[12][2])
        self.eq_param_12_q.setValue(params[12][3])

        self.eq_param_13_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[13][0]))
        self.eq_param_13_gain.setValue(params[13][1])
        self.eq_param_13_fc.setValue(params[13][2])
        self.eq_param_13_q.setValue(params[13][3])

        self.eq_param_14_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[14][0]))
        self.eq_param_14_gain.setValue(params[14][1])
        self.eq_param_14_fc.setValue(params[14][2])
        self.eq_param_14_q.setValue(params[14][3])

        self.eq_param_15_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[15][0]))
        self.eq_param_15_gain.setValue(params[15][1])
        self.eq_param_15_fc.setValue(params[15][2])
        self.eq_param_15_q.setValue(params[15][3])

        self.eq_param_16_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[16][0]))
        self.eq_param_16_gain.setValue(params[16][1])
        self.eq_param_16_fc.setValue(params[16][2])
        self.eq_param_16_q.setValue(params[16][3])

        self.eq_param_17_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[17][0]))
        self.eq_param_17_gain.setValue(params[17][1])
        self.eq_param_17_fc.setValue(params[17][2])
        self.eq_param_17_q.setValue(params[17][3])

        self.eq_param_18_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[18][0]))
        self.eq_param_18_gain.setValue(params[18][1])
        self.eq_param_18_fc.setValue(params[18][2])
        self.eq_param_18_q.setValue(params[18][3])

        self.eq_param_19_type.setCurrentText(eq_editor.iir_type_t_convert_int_to_str(params[19][0]))
        self.eq_param_19_gain.setValue(params[19][1])
        self.eq_param_19_fc.setValue(params[19][2])
        self.eq_param_19_q.setValue(params[19][3])

        return True

    def _save_ui_config_to_temp_file(self, section: str, key: str, value: str):
        print("==========================_save_ui_config_to_temp_file", section, key, value)
        config = configparser.ConfigParser()
        config.read(TEMP_CONFIG_FILE_PATH, encoding="utf8")
        if not config.has_section(section):
            config.add_section(section)
        config.set(section, key, value)
        try:
            fd = open(TEMP_CONFIG_FILE_PATH, "w", encoding="utf8")
            config.write(fd)
            fd.close()
            print("==========================_save_ui_config_to_temp_file success", section, key, value)
        except Exception as e:
            self._print_log(LEVEL_WARN, "Save ui config to temp file [Failed], file operation failed.")
        return True

    def _get_ui_config_from_temp_file(self, section: str, key: str):
        if not section or not key:
            return None
        if not os.path.isfile(TEMP_CONFIG_FILE_PATH):
            return None
        config = configparser.ConfigParser()
        config.read(TEMP_CONFIG_FILE_PATH, encoding="utf8")
        if not config.has_option(section, key):
            return None
        else:
            return config.get(section, key)
